/*******************************************************************************
 *    系统名称   : 约汗乐动力接口/后台管理系统
 *    客户             : 约汗乐动力
 *    文件名        ： HttpUtil.java
 *              (C) Copyright 博智乐创 Corporation 2015
 *               All Rights Reserved.
 *              http://www.bozlc.com
 * *****************************************************************************
 *    注意： 本内容仅限于约汗乐动力软件公司内部使用，未经许可禁止转发
 ******************************************************************************/
package com.xiake.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// TODO: Auto-generated Javadoc
/**
 * The Class HttpUtil.
 */
public class HttpUtil {
	
	/** The Constant logger. */
	private static final Logger logger = LoggerFactory.getLogger("httpclient");
	
	/** The Constant default_charaset. */
	private static final String default_charaset="utf-8";
	
	/** The Constant default_connect_timeout. */
	private static final int default_connect_timeout = 3000;
	
	/** The Constant default_socket_timeout. */
	private static final int default_socket_timeout = 3000;
	
	/** The Constant default_retries. */
	private static final int default_retries = 1;
	
	/**
	 * Make http client.
	 *
	 * @param socketTimeout the socket timeout
	 * @param connectTimeout the connect timeout
	 * @param retries the retries
	 * @param charset the charset
	 * @return the http client
	 */
	private static HttpClient makeHttpClient(int socketTimeout, int connectTimeout, int retries, String charset){
		HttpClient client = new HttpClient();
        HttpClientParams clientParams = client.getParams();
        clientParams.setParameter("http.socket.timeout", socketTimeout); 
        clientParams.setParameter("http.connection.timeout", connectTimeout); 
        // connection建立超时
        clientParams.setParameter("http.connection-manager.timeout", new Long(socketTimeout));
        clientParams.setParameter("http.method.retry-handler",
                new DefaultHttpMethodRetryHandler(retries, false)); // 如果Http出错，三次重试
        
        clientParams.setContentCharset(charset);//设置请求编码
        return client;
	}
	
	 /**
 	 * Post by form.
 	 *
 	 * @param url the url
 	 * @param params the params
 	 * @param connectTimeout the connect timeout
 	 * @param socketTimeout the socket timeout
 	 * @param retries the retries
 	 * @param charset the charset
 	 * @return the string
 	 * @throws Exception the exception
 	 */
 	public static String postByForm(String url, Map<String,String> params, int connectTimeout, int socketTimeout, int retries, String charset) throws Exception {
		    HttpClient client = makeHttpClient(connectTimeout, socketTimeout, retries, charset);
	        PostMethod post = new PostMethod(url);
	        String jsonStr = "";
	        InputStream ins = null;
	        try {
	        	post.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset="+charset); 
	            
	            if(params!=null&&!params.isEmpty()){
	                NameValuePair[] paramsPair = new NameValuePair[params.size()];
	                Iterator<Map.Entry<String,String>> iter = params.entrySet().iterator();//采用高效遍历法
	                int i=0;
	                while (iter.hasNext()) {
	                    Map.Entry<String,String> entry = (Map.Entry<String,String>)iter.next();
	                    NameValuePair jsonArry = new NameValuePair(entry.getKey(),entry.getValue());
	                    paramsPair[i] = jsonArry;
	                    i = i+1;
	                }
	                post.setRequestBody(paramsPair);
	            } 
	            int status = client.executeMethod(post);
	            if(status == HttpStatus.SC_OK){  
	                jsonStr = post.getResponseBodyAsString();
	            }else{
	                post.abort();//断连接
	            }
	            logger.info("url:"+url+",post,"+status);
	        } catch (Exception e) {
	            throw e;//错误日志在调用层根据类型记录
	        }finally{
	            if (null != ins) {
	                try {
	                    ins.close();
	                } catch (IOException e) {
	                }
	            }
	            if(null != post){
	                post.releaseConnection();
	            }
	        }
	        return jsonStr;
	    }

	/**
	 * set encoding for params, Do Not use URLEncode.encode() when invoke this method.
	 *
	 * @param url the url
	 * @param params the params
	 * @param connectTimeout the connect timeout
	 * @param socketTimeout the socket timeout
	 * @param retries the retries
	 * @param charset the charset
	 * @return the string
	 * @throws Exception the exception
	 */
	  public static String post(String url, Map<String,String> params, int connectTimeout, int socketTimeout, int retries, String charset) throws Exception {
		    HttpClient client = makeHttpClient(connectTimeout, socketTimeout, retries, charset);
	        PostMethod post = new PostMethod(url);
	        String jsonStr = "";
	        InputStream ins = null;
	        try {
	            post.addRequestHeader("Content-type","text/html;charset="+charset); 
	            
	            if(params!=null&&!params.isEmpty()){
	                NameValuePair[] paramsPair = new NameValuePair[params.size()];
	                Iterator<Map.Entry<String,String>> iter = params.entrySet().iterator();//采用高效遍历法
	                int i=0;
	                while (iter.hasNext()) {
	                    Map.Entry<String,String> entry = (Map.Entry<String,String>)iter.next();
	                    NameValuePair jsonArry = new NameValuePair(entry.getKey(),entry.getValue());
	                    paramsPair[i] = jsonArry;
	                    i = i+1;
	                }
	                post.setQueryString(paramsPair);
	            } 
	            int status = client.executeMethod(post);
	            if(status == HttpStatus.SC_OK){  
	                jsonStr = post.getResponseBodyAsString();
	            }else{
	                post.abort();//断连接
	            }
	            logger.info("url:"+url+",post,"+status);
	        } catch (Exception e) {
	            throw e;//错误日志在调用层根据类型记录
	        }finally{
	            if (null != ins) {
	                try {
	                    ins.close();
	                } catch (IOException e) {
	                }
	            }
	            if(null != post){
	                post.releaseConnection();
	            }
	        }
	        return jsonStr;
	    }
	  
	    /**
    	 * Post.
    	 *
    	 * @param url the url
    	 * @param params the params
    	 * @return the string
    	 * @throws Exception the exception
    	 */
    	public static String post(String url, Map<String,String> params) throws Exception {
	        return post(url, params, default_connect_timeout, default_socket_timeout, default_retries, default_charaset);
	    }
	    
	    
	    /**
    	 * 如果是中文，必须对参数进行编码才能传进来.
    	 *
    	 * @param url the url
    	 * @param headers the headers
    	 * @param paramsMap the params map
    	 * @param connectTimeout the connect timeout
    	 * @param socketTimeout the socket timeout
    	 * @param retries the retries
    	 * @param charset the charset
    	 * @return the string
    	 * @throws Exception the exception
    	 */
	    public static String get(String url, Map<String,String> headers,
	            Map<String,String> paramsMap, int connectTimeout, int socketTimeout, int retries, String charset) throws Exception {
	        HttpClient client = makeHttpClient(connectTimeout, socketTimeout, retries, charset);   
	        
            if(paramsMap!=null && !paramsMap.isEmpty()){
                Set<String> it = paramsMap.keySet();
                for (String key : it) {
                    String value = paramsMap.get(key);
                    if(url.contains("?"))
                    	url += "&";
                    else 
                    	url += "?";
                    url += key + "=" + value;
                }
            }
	        
	        GetMethod getMethod = new GetMethod(url);
	        getMethod.addRequestHeader("Content-type","text/html;charset="+charset);
	        if(headers!=null&&!headers.isEmpty()){
	            Iterator<Map.Entry<String,String>> iter = headers.entrySet().iterator();//采用高效遍历法
	            while (iter.hasNext()) {
	                Map.Entry<String,String> entry = (Map.Entry<String,String>)iter.next();
	                getMethod.addRequestHeader(entry.getKey(),entry.getValue());
	            }
	        }
	        
	        String jsonStr = "";
	        InputStream ins = null;
	        try {
	            int status = client.executeMethod(getMethod);
	            if(status == HttpStatus.SC_OK){ 
	                //判断如果是GZIP格式则进行解压
	                if(null!=getMethod.getResponseHeader("Content-Encoding")){
	                    if(getMethod.getResponseHeader("Content-Encoding").getValue().trim().equalsIgnoreCase("gzip")){
	                        ins = getMethod.getResponseBodyAsStream();
	                        jsonStr =uncompress(ins, default_charaset);
	                    }else{              
	                        jsonStr = getMethod.getResponseBodyAsString();
	                    }
	                }else{
	                    jsonStr = getMethod.getResponseBodyAsString();
	                }
	                //responseJson = JSONObject.fromObject(jsonStr); 
	                //responseJson.put("code", status);
	            }else{
	                getMethod.abort();//断连接
	            }
	            logger.info("url:"+url+",get,"+status);
	        }catch (Exception e) {
	            throw e;//错误日志在调用层根据类型记录
	        }finally{
	            if (null != ins) {
	                try {
	                    ins.close();
	                } catch (IOException e) {
	                }
	            }
	            if(null != getMethod){
	                getMethod.releaseConnection();
	            }
	        }
	        return jsonStr;
	    }
	    
	    
	    /**
    	 * Gets the.
    	 *
    	 * @param url the url
    	 * @param params the params
    	 * @param charset the charset
    	 * @return the string
    	 * @throws Exception the exception
    	 */
    	public static String get(String url,  Map<String, String> params, String charset) throws Exception {
	    	return get(url, null, params, default_connect_timeout, default_socket_timeout, default_retries, charset);
	    }
	    
	    /**
    	 * Gets the.
    	 *
    	 * @param url the url
    	 * @param params the params
    	 * @return the string
    	 * @throws Exception the exception
    	 */
    	public static String get(String url, Map<String, String> params) throws Exception{
	    	return get(url, null, params);
	    }
	    
    	/**
    	 * Gets the.
    	 *
    	 * @param url the url
    	 * @param params the params
    	 * @param timeout the timeout
    	 * @return the string
    	 * @throws Exception the exception
    	 */
    	public static String get(String url, Map<String, String> params,int timeout) throws Exception{
	    	return get(url,null,params,timeout,timeout, default_retries, default_charaset);
	    }
	    
    	/**
    	 * Gets the.
    	 *
    	 * @param url the url
    	 * @param headers the headers
    	 * @param paramsMap the params map
    	 * @return the string
    	 * @throws Exception the exception
    	 */
	    public static String get(String url, Map<String,String> headers,
	            Map<String, String> paramsMap) throws Exception {
	        return get(url, headers, paramsMap, default_connect_timeout, default_socket_timeout, default_retries, default_charaset);
	    }
	    
	    /**
    	 * Uncompress.
    	 *
    	 * @param in the in
    	 * @param charset the charset
    	 * @return the string
    	 * @throws IOException Signals that an I/O exception has occurred.
    	 */
    	public static String uncompress(InputStream in,String charset) throws IOException{
           GZIPInputStream gInputStream = new GZIPInputStream(in);
           byte[] by = new byte[1024];
           StringBuffer strBuffer = new StringBuffer();
           int len = 0;
           while ((len = gInputStream.read(by)) != -1) {
               strBuffer.append( new String(by, 0, len,charset) );
           }
           return strBuffer.toString();
	    }
	    
	    /*
	     * GZIP压缩字符串
	     */   
	    /**
    	 * Compress str.
    	 *
    	 * @param str the str
    	 * @param charset the charset
    	 * @return the string
    	 * @throws IOException Signals that an I/O exception has occurred.
    	 */
    	public static String compressStr(String str,String charset) throws IOException {   
	        if (str == null || str.length() == 0) {   
	            return str;   
	        }   
	        ByteArrayOutputStream out = new ByteArrayOutputStream();   
	        GZIPOutputStream gzip = new GZIPOutputStream(out);   
	        gzip.write(str.getBytes(charset)); 
	        gzip.close();   
	        return out.toString("ISO-8859-1");   
	    }   
	     
	    /*
	     * GZIP解压字符串
	     */   
	    /**
    	 * Uncompress str.
    	 *
    	 * @param str the str
    	 * @param charset the charset
    	 * @return the string
    	 * @throws IOException Signals that an I/O exception has occurred.
    	 */
    	public static String uncompressStr(String str,String charset) throws IOException {   
	       if (str == null || str.length() == 0) {   
	           return str;   
	       }   
	       ByteArrayOutputStream out = new ByteArrayOutputStream();   
	       ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));   
	       GZIPInputStream gunzip = new GZIPInputStream(in);   
	       byte[] buffer = new byte[256];   
	       int n;   
	       while ((n = gunzip.read(buffer))>= 0) {   
	           out.write(buffer, 0, n);   
	       }      
	       return out.toString(charset);   
	     }  
}
